#include "csginternode.h"
#include "csgprimitivenode.h"

CSGInterNode::CSGInterNode(Expression& e1, Expression& e2)
    :CSGNode(0)
{
    addChild(new CSGPrimitiveNode(e1, this));
    addChild(new CSGPrimitiveNode(e2, this));
}

CSGInterNode::CSGInterNode(CSGNode *left, Expression& e)
    :CSGNode(0)
{
    addChild(left);
    addChild(new CSGPrimitiveNode(e, this));
}

CSGInterNode::CSGInterNode(Expression& e, CSGNode *right)
    :CSGNode(0)
{
    addChild(new CSGPrimitiveNode(e, this));
    addChild(right);
}

CSGInterNode::CSGInterNode(CSGNode *left, CSGNode *right)
    :CSGNode(0)
{
    addChild(left);
    addChild(right);
}

double CSGInterNode::eval(double x, double y, double z)
{
    return std::max(((CSGNode*)getChild(0))->eval(x,y,z), ((CSGNode*)getChild(1))->eval(x,y,z));
}

bool CSGInterNode::emptyTest(StarTestBox *box)
{
    bool boundary = false;

    for (int i = 0; i < getNumChild(); i++)
    {
        ((CSGNode*)getChild(i))->emptyTest(box);

        if (box->isOuter())
        {
            break;
        }
        else if (box->isBoundary())
        {
            boundary = true;
        }
    }

    if (!box->isOuter() && boundary)
    {
        box->pos = BOX_BOUNDARY;
    }

    return box->isOuter();
}

bool CSGInterNode::starTest(StarTestBox *box, double *pt)
{
    for (int i = 0; i < getNumChild(); i++)
    {
        box->pos = BOX_UNKNOWN;
        if (!((CSGNode*)getChild(i))->starTest(box, pt))
        {
            break;
        }
    }

    return box->isStar();
}

bool CSGInterNode::complementStarTest(StarTestBox *box, double *pt)
{
    for (int i = 0; i < getNumChild(); i++)
    {
        box->pos = BOX_UNKNOWN;
        if (!((CSGNode*)getChild(i))->complementStarTest(box, pt) && !box->isOuter())
        {
            break;
        }
        box->pos = BOX_STAR;
    }

    return box->isStar();
}

bool CSGInterNode::ptInSet(double *pt)
{
    for (int i = 0; i < getNumChild(); i++)
    {
        if (!((CSGNode*)getChild(i))->ptInSet(pt))
        {
            return false;
        }
    }

    return true;
}
